﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;

namespace InfoPathHelpers
{
    /// <summary>
    /// FixedPositionNavigator root wraps an XPathNavigator object to make a fixed position navigator
    /// i.e. only operations that to not change the position are exposed.
    /// </summary>
    public class FixedPositionNavigator
    {
        private XPathNavigator _Navigator;

        /// <summary>
        /// Creates a new instance of FixedPositionNavigator using the supplied XPathNavigator.
        /// </summary>
        /// <param name="root">The XPathNavigator</param>
        public FixedPositionNavigator(XPathNavigator root)
        {
            _Navigator = root;
        }

        /// <summary>
        /// Gets the URI for the current node.
        /// </summary>
        public string BaseURI
        {
            get { return _Navigator.BaseURI; }
        }

        /// <summary>
        /// Gets a value indicating whether the node has any attributes.
        /// </summary>
        public bool HasAttributes
        {
            get { return _Navigator.HasAttributes; }
        }

        /// <summary>
        /// Gets a value indicating whether the node has any child nodes.
        /// </summary>
        public bool HasChildren
        {
            get { return _Navigator.HasChildren; }
        }

        /// <summary>
        /// Gets or sets the markup representing the child nodes of the current node.
        /// </summary>
        public string InnerXml
        {
            get { return _Navigator.InnerXml; }
        }

        /// <summary>
        /// Gets a value indicating whether the current node is an empty element without an element tag.
        /// </summary>
        public bool IsEmptyElement
        {
            get { return _Navigator.IsEmptyElement; }
        }

        /// <summary>
        /// Gets a value indicating if the current node represents an XPath node.
        /// </summary>
        public bool IsNode
        {
            get { return _Navigator.IsNode; }
        }

        /// <summary>
        /// Gets the name of the current node without any namespace prefix.
        /// </summary>
        public string LocalName
        {
            get { return _Navigator.LocalName; }
        }

        /// <summary>
        /// Gets the qualified name of the current node.
        /// </summary>
        public string Name
        {
            get { return _Navigator.Name; }
        }

        /// <summary>
        /// Gets the namespace URI of the current node.
        /// </summary>
        public string NamespaceURI
        {
            get { return _Navigator.NamespaceURI; }
        }

        /// <summary>
        /// Gets or sets the markup representing the opening and closing tags of the current node and its child nodes.
        /// </summary>
        public string OuterXml
        {
            get { return _Navigator.OuterXml; }
        }

        /// <summary>
        /// Gets the namespace prefix associated with the current node.
        /// </summary>
        public string Prefix
        {
            get { return _Navigator.Prefix; }
        }

        /// <summary>
        /// Gets the string value of the current node.
        /// </summary>
        public string Value
        {
            get { return _Navigator.Value; }
        }

        /// <summary>
        /// Selects a single node in the System.Xml.XPath.XPathNavigator object using 
        /// the specified XPath query.
        /// </summary>
        /// <param name="xPath">A System.String representing an XPath expression.</param>
        /// <returns>An System.Xml.XPath.XPathNavigator object that contains the first matching
        /// node for the XPath query specified; otherwise, null if there are no query
        /// results.</returns>
        public XPathNavigator SelectSingleNode(string xPath)
        {
            return _Navigator.SelectSingleNode(xPath);
        }

        /// <summary>
        /// Selects a single node in the System.Xml.XPath.XPathNavigator object using
        /// the specified XPath query with the System.Xml.IXmlNamespaceResolver object
        /// specified to resolve namespace prefixes.
        /// </summary>
        /// <param name="xPath">A System.String representing an XPath expression.</param>
        /// <param name="resolver">The System.Xml.IXmlNamespaceResolver object used to resolve namespace prefixes
        /// in the XPath query.</param>
        /// <returns>An System.Xml.XPath.XPathNavigator object that contains the first matching
        /// node for the XPath query specified; otherwise, null if there are no query
        /// results.</returns>
        public XPathNavigator SelectSingleNode(string xPath, IXmlNamespaceResolver resolver)
        {
            return _Navigator.SelectSingleNode(xPath, resolver);
        }

        /// <summary>
        /// Selects a node set, using the specified XPath expression.
        /// </summary>
        /// <param name="xPath">A System.String representing an XPath expression.</param>
        /// <returns>An System.Xml.XPath.XPathNodeIterator pointing to the selected node set.</returns>
        public XPathNodeIterator Select(string xPath)
        {
            return _Navigator.Select(xPath);
        }

        /// <summary>
        /// Selects a node set using the specified XPath expression with the System.Xml.IXmlNamespaceResolver
        /// object specified to resolve namespace prefixes.
        /// </summary>
        /// <param name="xPath">A System.String representing an XPath expression.</param>
        /// <param name="resolver">The System.Xml.IXmlNamespaceResolver object used to resolve namespace prefixes.</param>
        /// <returns>An System.Xml.XPath.XPathNodeIterator that points to the selected node set.</returns>
        public XPathNodeIterator Select(string xPath, IXmlNamespaceResolver resolver)
        {
            return _Navigator.Select(xPath, resolver);
        }

        /// <summary>
        /// Evaluates the specified XPath expression and returns the typed result.
        /// </summary>
        /// <param name="xPath">A string representing an XPath expression that can be evaluated.</param>
        /// <returns>The result of the expression (Boolean, number, string, or node set). This
        /// maps to System.Boolean, System.Double, System.String, or System.Xml.XPath.XPathNodeIterator
        /// objects respectively.</returns>
        public object Evaluate(string xPath)
        {
            return _Navigator.Evaluate(xPath);
        }

        /// <summary>
        /// Evaluates the specified XPath expression and returns the typed result, using
        /// the System.Xml.IXmlNamespaceResolver object specified to resolve namespace
        /// prefixes in the XPath expression.
        /// </summary>
        /// <param name="xPath">A string representing an XPath expression that can be evaluated.</param>
        /// <param name="namespaceManager">The System.Xml.IXmlNamespaceResolver object used to resolve namespace prefixes
        /// in the XPath expression.</param>
        /// <returns>The result of the expression (Boolean, number, string, or node set). This
        /// maps to System.Boolean, System.Double, System.String, or System.Xml.XPath.XPathNodeIterator
        /// objects respectively.</returns>
        public object Evaluate(string xPath, IXmlNamespaceResolver namespaceManager)
        {
            return _Navigator.Evaluate(xPath, namespaceManager);
        }

        /// <summary>
        /// When overridden in a derived class, creates a new System.Xml.XPath.XPathNavigator
        /// positioned at the same node as this System.Xml.XPath.XPathNavigator.
        /// </summary>
        /// <returns>A new System.Xml.XPath.XPathNavigator positioned at the same node as this
        /// System.Xml.XPath.XPathNavigator.</returns>
        public XPathNavigator Clone()
        {
            return _Navigator.Clone();
        }
    }
}
